#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <DHT.h>
#include <WiFi.h>
#include <BH1750FVI.h>
#include <OneWire.h>
#include <ESP32Servo.h>

const char *ssid = "ziroom602";//WIFI
const char *password = "4001001111";//WIFI密码
const char* serverIP = "183.230.40.33"; //欲访问的地址
uint16_t serverPort = 80;         //服务器端口号
String url = "http://api.heclouds.com/devices/762634087/datapoints?type=3";//网址 设备ID
String api="h8tpETsrj==4tTdrjbSgYFNsgW4=";//api-key
String post;//http请求
int Content_Length;
WiFiClient client; //声明一个客户端对象，用于与服务器进行连接

OneWire  ds(0);  // on pin 10 (a 4.7K resistor is necessary)
BH1750FVI myBH1750(BH1750_DEFAULT_I2CADDR, BH1750_CONTINUOUS_HIGH_RES_MODE_2, BH1750_SENSITIVITY_DEFAULT, BH1750_ACCURACY_DEFAULT);
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18, /* data=*/ 19, /* cs=*/ 5, /* dc=*/ 16, /* reset=*/ 17);
Servo myservo;  // create servo object to control a servo
#define DHTTYPE       DHT11 //选择的类型


int     servoPin    = 14;      // GPIO pin used to connect the servo control (digital out)
#define LED_BUILTIN   02
#define WATER         15
#define GROUND_H      4
#define WATER_MOTOR   12 //
#define O2_MOTOR      13
#define BEEP          33
#define DHTPIN        27 //DHT11 DATA 数据引脚
DHT dht(DHTPIN, DHTTYPE);
long  ground_h = 0, water = 0, pwm_value = 0;
float tank_temp = 0, house_h = 0, house_t = 0, light_value = 0;
int8_t rx_data = 0, beep_flag = 0, water_ok_flag = 0, water_in_flag = 0, O2_in_flag = 0;
static unsigned long time_=0;//定义初始发送时间为0
static unsigned long time_out=0;//定义超时发送时间为0

void setup(void)
{
    //DHT11
    dht.begin();  

    //OLED
    u8g2.begin();
    u8g2.enableUTF8Print();        // enable UTF8 support for the Arduino print() function

    //USART
    Serial.begin(9600);

    //PIN CFG
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(WATER_MOTOR, OUTPUT);
    pinMode(O2_MOTOR, OUTPUT); 
    pinMode(BEEP, OUTPUT);
    digitalWrite(BEEP, 1); //low - beep

    pinMode(GROUND_H, INPUT);
    pinMode(GROUND_H, INPUT_PULLUP);
    pinMode(WATER, INPUT);
    pinMode(WATER, INPUT_PULLUP);

    //WIFI
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);//连接到网络

   while (WiFi.status() != WL_CONNECTED) {//等待网络连接成功
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());//打印模块IP

    //BH1750
    while (myBH1750.begin() != true)               
    {
        Serial.println(F("ROHM BH1750FVI is not present")); //(F()) saves string to flash & keeps dynamic memory free
        delay(5000);
    }
    Serial.println(F("ROHM BH1750FVI is present"));

    
    //PWM & MOTOR
    ESP32PWM::allocateTimer(0);
	ESP32PWM::allocateTimer(1);
	ESP32PWM::allocateTimer(2);
	ESP32PWM::allocateTimer(3);
    myservo.setPeriodHertz(50);// Standard 50hz servo
    myservo.attach(servoPin, 500, 2400); 
}

void loop(void)
{
    byte i;
    byte present = 0;
    byte type_s;
    byte data[12];
    byte addr[8];
    float celsius, fahrenheit;

    //DS18B20
    if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
    }

    if (OneWire::crc8(addr, 7) != addr[7]) {
        Serial.println("CRC is not valid!");
        return;
    }

    switch (addr[0]) {
        case 0x10:
        //Serial.println("  Chip = DS18S20");  // or old DS1820
        type_s = 1;
        break;
        case 0x28:
        //Serial.println("  Chip = DS18B20");
        type_s = 0;
        break;
        case 0x22:
       // Serial.println("  Chip = DS1822");
        type_s = 0;
        break;
        default:
        Serial.println("Device is not a DS18x20 family device.");
        return;
    } 

    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);        // start conversion, with parasite power on at the end  
    delay(1000);     // maybe 750ms is enough, maybe not
    present = ds.reset();
    ds.select(addr);    
    ds.write(0xBE);         // Read Scratchpad

    for ( i = 0; i < 9; i++) {           // we need 9 bytes
        data[i] = ds.read();
    }

    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
        raw = raw << 3; // 9 bit resolution default
        if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
        }
    } else {
        byte cfg = (data[4] & 0x60);
        // at lower res, the low bits are undefined, so let's zero them
        if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
        else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
        else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
        //// default is 12 bit resolution, 750 ms conversion time
    }
    celsius = (float)raw / 16.0;
    fahrenheit = celsius * 1.8 + 32.0;
    tank_temp = celsius;
    
    //DHT11
    house_h = dht.readHumidity();
    house_t = dht.readTemperature();
    
    
     if (isnan(house_h) || isnan(house_t))
     {
         Serial.println("Failed to read from DHT sensor!");
         return;
     }

     //BH1750
    light_value = myBH1750.readLightLevel();


    //logic
    ground_h = 1-digitalRead(GROUND_H);
    water = 1-digitalRead(WATER);
    Serial.printf("GROUND-WATER: %d,%d",ground_h,water);
    Serial.println("//");
    digitalWrite(WATER_MOTOR, 1-ground_h); //HIGH-OPEN ground h low  open water motor
    digitalWrite(O2_MOTOR, water);//no use

    if(light_value >= 50)
        pwm_value = 180;
    else if(light_value <= 20)
        pwm_value = 0;
    
    if((tank_temp>30) || (tank_temp<20))
    {
        digitalWrite(BEEP, 0); //low - beep
    }
    else digitalWrite(BEEP, 1);

    //MOTOR 
    myservo.write(pwm_value);                  // set the servo position according to the scaled value  (value between 0 and 180)

    //LED
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);

    //OLED
    u8g2.setFont(u8g2_font_unifont_t_chinese2);
    u8g2.clearBuffer(); //清除模组的缓存
    u8g2.setFont(u8g2_font_ncenB08_tr); // 设置字体
    u8g2.setCursor(0, 15);
    u8g2.printf("TEMP-WATER: %.2fC", tank_temp);
    u8g2.setCursor(0, 30);
    u8g2.printf("GOUND:%d WATER:%d",ground_h, water);
    u8g2.setCursor(0, 45);
    u8g2.printf("HOUSE-TH: %.1fC,%.1f%",house_t,house_h); 
    u8g2.setCursor(0, 60);
    u8g2.printf("LIGHT-LUX: %.2fLux",light_value);
    u8g2.sendBuffer(); // 将缓存输出到屏幕

   
    // if (!client.connect(serverIP, serverPort)) {//判断是否连接服务器
    //     Serial.println("connection failed");
    //     return;
    // }else{//连接成功
    //    //Serial.println("connection succ");
    //    //Serial.println();
    //    String data_value="{\"tank_temp\":"+String(tank_temp)+",\"ground_h\":"+String(ground_h)
    //       +",\"house_h\":"+String(1)+",\"house_t\":"+String(1)
    //       +",\"light_value\":"+String(light_value)+",\"O2_in_flag\":"+String(O2_in_flag)
    //       +",\"test\":"+String(beep_flag)+"}\r\n\r\n";
    // //  String data_value="{\"tank_temp\":"+String(tank_temp)+",\"ground_h\":"+String(ground_h)
    // //         +"}\r\n\r\n";

    //    Content_Length=data_value.length();
    //    post=String("POST ")+url+" HTTP/1.1\r\n"+"api-key: "+api+"\r\n"
    //       +"Host:api.heclouds.com\r\n"+"Connection:close\r\n"+"Content-Length:"
    //       +String(Content_Length)+"\r\n\r\n"+data_value;
          
    //     // Serial.println(Content_Length);
    //     // Serial.print(post);//串口打印HTTP请求
    //     //client.print(post);//向服务器发送HTTP请求
    //   }
    //    while(client.available()) {//判断WIFI是否有数据
    //     Serial.print(post);
    //     String line = client.readStringUntil('\r');//读取WIFI数据赋给line
    //     Serial.print(line);//打印line 
    // }
}
